import socket
import threading

from handler import BaseHandler
from utils import logging

class TCPClient(object):

    def __init__(self, server_address: tuple, handler_cls):
        self.server_address = server_address
        self.handler_cls = handler_cls

        self.__socket: socket.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.th_event = threading.Event()
        self.__is_shutdown: bool = True

    def connect(self):
        self.th_event.clear()
        self.__is_shutdown = False

        try:
            self.__socket.connect(self.server_address)
        except ConnectionRefusedError:
            self.close()
            logging.info("连接服务器失败, 请检查地址和端口")

            return

        # 启动监听, 监听响应的信息
        threading.Thread(target=self.rece_message).start()

    def rece_message(self):
        self.handler: BaseHandler = self.handler_cls(self, self.__socket, self.server_address)

        while self.is_connected:
            try:
                data: bytes = self.__socket.recv(self.handler.recv_len)

            except ConnectionResetError:
                """
                异常处理, ConnectionResetError 远程主机主动断开连接
                该异常是对方主动与我方断开连接, 
                """

                self.handler.on_connect_err('ConnectionResetError', descriotion="远程主机主动断开连接")

                break

            except ConnectionAbortedError:
                """
                异常处理, ConnectionAbortedError 你的主机中软件终止了一个已建立的连接
                该异常是我方主动与对方断开连接, 
                """

                self.handler.on_connect_err('ConnectionAbortedError', descriotion="你的主机中软件终止了一个已建立的连接")

                break

            except:
                """
                异常处理, 奇奇怪怪的异常处理,
                该异常处理其他异常
                """
                self.handler.on_connect_err('OtherError', descriotion="异常处理, 奇奇怪怪的异常处理")

                break

            self.handler.on_message(data = data)

        self.close()

        return False

    def send(self, data_type: str, data: str):
        try:
            self.handler.send(data_type, data)
        except Exception as e:
            print(e)
            self.handler.on_connect_err('OtherError', descriotion="异常处理, 奇奇怪怪的异常处理")

            self.close()
            return

    def close(self):
        self.th_event.wait()
        self.__is_shutdown = True

        try:
            self.__socket.close()
        except Exception:
            pass

    def on_disconnection(self, remote_address: tuple):
        exit()

    @property
    def is_connected(self):
        return not self.__is_shutdown


class SimpeHandler(BaseHandler):

    def handle(self, data_type, data):
        logging.info("Received {host}: {data}".format(host="%s:%d" % (self.remote_address[0], self.remote_address[1]),
                                                      data=data))

if __name__ == '__main__':
    client = TCPClient(server_address=("127.0.0.1", 8080), handler_cls=SimpeHandler)
    client.connect()

    while client.is_connected:
        data = input()

        if data == "exit":
            client.close()
            break

        client.send("text", data)
